package gov.pbc.nn.kjgl.maintenance.view;

import gov.pbc.nn.core.bdf.entity.Dept;
import gov.pbc.nn.core.dao.CommonHibernateDao;
import gov.pbc.nn.core.dao.CommonJdbcDao;
import gov.pbc.nn.core.dao.PbcnnCoreHibernateDao;
import gov.pbc.nn.core.utils.EntityRowMapperUtils;
import gov.pbc.nn.core.utils.SecurityUtils;
import gov.pbc.nn.kjgl.maintenance.entity.SysEntity;
import gov.pbc.nn.kjgl.maintenance.entity.SysEvent;
import gov.pbc.nn.uflo.UfloUtils;

import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import javax.annotation.Resource;

import org.apache.commons.lang3.StringUtils;
import org.hibernate.Session;
import org.hibernate.criterion.DetachedCriteria;
import org.hibernate.criterion.MatchMode;
import org.hibernate.criterion.Restrictions;
import org.springframework.jdbc.core.RowMapper;
import org.springframework.stereotype.Component;
import org.springframework.transaction.annotation.Transactional;

import com.bstek.bdf2.core.context.ContextHolder;
import com.bstek.bdf2.core.orm.ParseResult;
import com.bstek.bdf2.core.orm.hibernate.ISessionCallback;
import com.bstek.dorado.annotation.DataProvider;
import com.bstek.dorado.annotation.DataResolver;
import com.bstek.dorado.annotation.Expose;
import com.bstek.dorado.data.entity.EntityState;
import com.bstek.dorado.data.entity.EntityUtils;
import com.bstek.dorado.data.provider.Criteria;
import com.bstek.dorado.data.provider.Page;
import com.bstek.uflo.client.service.ProcessClient;
import com.bstek.uflo.client.service.TaskClient;
import com.bstek.uflo.service.StartProcessInfo;

@Component
public class SysEventPR {

	@Resource(name = CommonHibernateDao.BEAN_ID)
	private CommonHibernateDao hibernateDao;
	@Resource(name = CommonJdbcDao.BEAN_ID)
	private CommonJdbcDao jdbcDao;
	@Resource(name = PbcnnCoreHibernateDao.BEAN_ID)
	private PbcnnCoreHibernateDao coreHibernateDao;
	@Resource(name = ProcessClient.BEAN_ID)
	private ProcessClient pc;
	@Resource(name = TaskClient.BEAN_ID)
	private TaskClient tc;

	public static final String PROCESS_NAME = "系统事件管理";

	@DataProvider
	public void loadEvent(Page<SysEvent> page, Criteria criteria) {
		String sql = "";
		Map<String, Object> map = new HashMap<String, Object>();
		Dept dept = (Dept) ContextHolder.getLoginUser().getDepts().get(0);
		Dept zzDept = (Dept) SecurityUtils.getZZByDept(dept);
		if (Dept.NANNING.equals(zzDept.getId())) 
		{
			sql="select a.*,b.FILE_NAME_ from t_sys_event as a left join t_sys_material as b on a.SCHEME_ID_ =b.ID_ where a.INVALID_=0 order by a.CREATE_DATE_";
			ParseResult pr = jdbcDao.parseCriteria(criteria, true, null);
			if (pr != null) {
				StringBuffer sbSql = pr.getAssemblySql();
				sql += " and " + sbSql;
				map.putAll(pr.getValueMap());
			}
		}
		else {
			sql="select a.*,b.FILE_NAME_ from t_sys_event as a left join t_sys_material as b on a.SCHEME_ID_ =b.ID_ "
		       +" where a.INVALID_=0 and a.sys_id_ in (select s.id_ from T_SYS_ENTITY as s where s.INVALID_=0 and (s.DEPT_ID_ =:deptId or s.OPERATION_DEPT_ID_=:deptId)) "
			   +" order by a.CREATE_DATE_";
			ParseResult pr = jdbcDao.parseCriteria(criteria, true, "a");
			map.put("deptId", dept.getId());
			if (pr != null) {
				StringBuffer sbSql = pr.getAssemblySql();
				sql += " and " + sbSql;
				map.putAll(pr.getValueMap());
			}
		}
		
		this.jdbcDao.pagingQuery(page, sql, new RowMapper<SysEvent>() {
			@Override
			public SysEvent mapRow(ResultSet rs, int rowNum) throws SQLException {
				// TODO Auto-generated method stub
				SysEvent se = EntityRowMapperUtils.get(SysEvent.class, rs, rowNum);
				try {
					se = EntityUtils.toEntity(se);
				} catch (Exception e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
				}
				EntityUtils.setValue(se, "schemeName", rs.getString("FILE_NAME_"));
				return se;

			}
		}, map);

		// DetachedCriteria dc =
		// this.hibernateDao.buildDetachedCriteria(criteria, SysEvent.class);
		// dc.add(Restrictions.eq("invalid", false));
		// this.hibernateDao.pagingQuery(page, dc);
	}

	/**
	 * 加载系统信息。根据当前登录人是运维人员或某系统的业务人员加载
	 * 
	 * @param filter
	 * @return
	 */
	@DataProvider
	public  List<SysEntity> getSysEntities(String filter) {
		/*String sql = "select DISTINCT e.id_ as id,e.name_ as name,s.ab_ as ab from t_sys_entity e left join t_sys_operation_staff s on e.ID_=s.SYS_ID_ and s.INVALID_=0 and s.USERNAME_=? WHERE e.invalid_=0 and e.AUDIT_STATE_=2 ";
		Object[] param = null;
		if (StringUtils.isEmpty(filter)) {
			param = new Object[] { ContextHolder.getLoginUserName() };
		} else {
			sql += " AND e.NAME_ LIKE ? ";
			param = new Object[] { ContextHolder.getLoginUserName(), filter + "%" };
		}
		List<Map<String, Object>> mapList = this.jdbcDao.getJdbcTemplate().queryForList(sql, param);
		if (mapList.size() > 0) {

			List<String> sysIds = new ArrayList<String>();
			for (Map<String, Object> m : mapList) {
				sysIds.add((String) m.get("id"));
			}
			String hql = "select new map(e.id AS id,e.name as name) from "
					+ SysEntity.class.getName()
					+ " e where e.invalid=false and e.auditState=2 and e.operationDeptId=:deptId and e.id not in :sysIds";
			Map<String, Object> m = new HashMap<String, Object>();
			m.put("deptId", ContextHolder.getLoginUser().getDepts().get(0).getId());
			m.put("sysIds", sysIds);
			List<Map<String, Object>> mapList2 = this.hibernateDao.query(hql, m);
			mapList.addAll(mapList2);
		}

		return mapList;
		*/
		
		DetachedCriteria dc = DetachedCriteria.forClass(SysEntity.class);
		dc.add(Restrictions.eq("invalid", false));
		dc.add(Restrictions.eq("auditState", 2));
		Dept dept = (Dept) ContextHolder.getLoginUser().getDepts().get(0);
		Dept zzDept = (Dept) SecurityUtils.getZZByDept(dept);
		if (!Dept.NANNING.equals(zzDept.getId())) {
		dc.add(Restrictions.or(Restrictions.eq("deptId", dept.getId()), Restrictions.eq("operationDeptId", dept.getId())));
		}
		if (StringUtils.isNotBlank(filter)) {
			dc.add(Restrictions.like("name", "%"+filter+"%"));
		}
		return (List<SysEntity>) this.hibernateDao.query(dc);
		
	}

	@DataResolver
	@Transactional
	public void saveEvent(SysEvent event) {
		EntityState state = EntityUtils.getState(event);
		if (state == EntityState.NEW) {
			this.hibernateDao.save(event);
		} else {
			if (state == EntityState.MODIFIED) {
				this.hibernateDao.update(event);
			}
		}
	}

	@Expose
	@Transactional
	public void deleteEvent(final String id) {
		String result = this.canDelete(id);
		if(result!=null){
			throw new UnsupportedOperationException("result");
		}
		this.hibernateDao.delete(id, SysEvent.class);
		UfloUtils.deleteProcessInstance(id,true);
	}

	@Expose
	public String canDelete(String id) {
		if (UfloUtils.hasHistoryProcessInstance(id)) {
			return "当前任务已经审批完成，不能删除！";
		}
		return null;
	}

	@Expose
	public String canModify(String id) {
		if (UfloUtils.isInProcessInstance(id)) {
			return "当前任务正在审批过程中，不能修改！";
		}
		if (UfloUtils.hasHistoryProcessInstance(id)) {
			return "当前任务已经审批完成，不能修改！";
		}
		return null;
	}

	/**
	 * 开启流程
	 * 
	 * @param eventId
	 * @throws Exception
	 */
	@Transactional
	@DataResolver
	public void startProcess(SysEvent event) throws Exception {
		event.setState(5);
		EntityState state = EntityUtils.getState(event);
		if(state!=EntityState.NEW){
			EntityUtils.setState(event, EntityState.MODIFIED);
		}
		this.saveEvent(event);
		if (UfloUtils.isInProcessInstance(event.getId())) {
			throw new UnsupportedOperationException("当前任务正在审批过程中，不能重复发起申请！");
		}
		if (UfloUtils.hasHistoryProcessInstance(event.getId())) {
			throw new UnsupportedOperationException("当前任务已经审批完成，不能重复发起申请！");
		}
		Map<String, Object> variables = new HashMap<String, Object>();
		variables.put("sysId", event.getSysId());
		variables.put("taskname", "【" + event.getSysName() + "】系统事件,需运维人员处理");
		StartProcessInfo spi = new StartProcessInfo();
		spi.setBusinessId(event.getId());
		spi.setCompleteStartTask(true);
		spi.setPromoter(ContextHolder.getLoginUserName());
		spi.setVariables(variables);
		this.pc.startProcessByName(PROCESS_NAME, spi);
	}
}
